import { get } from "@/utils/request";
import { Message } from 'element-ui';
import store from '@/store'

// websocket封装
class GatewayImpl {
    constructor(config) {
        this._offline = false;
        this._connecting = false;
        this._onmessage = this._onmessage.bind(this);
        this._param = config.param || "";
        this._interval = 60 * 1000;
        this._url = '';
        this.uid = config.uid;
        // this._url = config.url;
        // this._http = config.http;
        // this._id = "GatewayImpl_" + Math.random().toString().slice(-10);
        // keys[this._id] = config.keys;
        this.close = this.close.bind(this);
        this.resetHeartbeat();
        // 建立连接
       this._conlink = this._tryReConnection();
    }

    get connectionState() {
        if (this._socket) {
            return this._socket.readyState;
        }
        return 3;
    }


    /**
     * 尝试获取一个可用的 WebSocket 连接
     * @param url
     * @param event
     */
    async _getWebsocket(url, event) {
        let socket = new WebSocket(url);
        // console.log("socket:",socket);
        // 等到连接可用
        return new Promise((resolve, reject) => {
            socket.onopen = (e) => {
                if (event && event.onopen)
                    event.onopen(e);
                resolve(socket);
            };
            socket.onclose = (e) => {
                // 关闭连接
                // console.log("断掉了-------");
                if (event && event.onclose)
                    event.onclose(e);
                reject(e);
            };
            socket.onerror = (e) => {
                // console.log("出错：",e);
                if (event && event.onerror)
                    event.onerror(e);
                reject(e);
            };
        });
    }


    /**
     * 尝试重新连接 (如果断开)
     * @param maxTime 最大重连时间 0 为不限制, 单位为毫秒
     */
    async _tryReConnection(maxTime = 0) {
        if (this._offline) {
            this.onoffline();
        }
        // console.log("_connecting:",this._connecting);
        if (this._connecting) {
            return this._conlink;
        }
        try {
            this._connecting = true;
            // console.log('发送重连：',this._socket,this._socket.readyState);
            // 连接不可用
            // console.log("状态：",this._socket?this._socket.readyState:"");
            if (!this._socket || this._socket.readyState !== 1) {
                let startTime = Date.now();
                // 尝试重连
                this._socket = await new Promise((resolve, reject) => {
                    get("msg/createWebSocket").then(res=>{
                        if (res.code == 1) {
                            this._url = res.data.url;
                        }else{
                            Message.error(res.msg);
                            store.commit("message/CHANGE_STASTE",true);
                            reject(new Error(res.msg));
                        }
                    }).catch(err=>{
                        Message.error("请求失败，请稍后重试");
                        store.commit("message/CHANGE_STASTE",true);
                        reject(new Error("请求失败，请稍后重试"));
                    })
                    const _connection = async () => {
                        // 重连的事件调用
                        // if (this.onreconnection) {
                        //     this.onreconnection();
                        // }
                        // 最大时间限制
                        if (maxTime > 0 && startTime + maxTime <= Date.now()) {
                            reject(new Error("WebSocket 重连超时."));
                            return;
                        }
                        try {
                            // console.log("this._url:",this._url+"?uid="+this.uid);
                            let socket = await this._getWebsocket(this._url+"?uid="+this.uid, this);
                            resolve(socket);
                        }
                        catch (e) {
                            setTimeout(() => _connection(), 1000);
                        }
                    };
                    _connection();
                });
                this._initSocket();
            }
        }
        finally {
            this._connecting = false;
        }
        return null;
    }

    _onmessage(event) {
        try {
            // console.log(event.data)
            if (!event.data || !this.onsockmessage)
                return;
            // 响应给监听者
            this.onsockmessage(event);
        }
        catch (e) {
            console.error(e);
        }
        finally {
            // 调用原 mesage 事件
            if( this.onmessage ) this.onmessage(event);
        }
    }


    _initSocket() {
        this._socket.onmessage = this._onmessage;
        this._socket.onopen = (event) => {
            
            return this.onopen && this.onopen(event);
        };
        this._socket.onclose = (event) => {
            if (this.onclose) {
                this.onclose(event);
            }
        };
        // onerror 在断网的情况下会不停地调用 
        this._socket.onerror = null;
        // this._socket.onerror = function (event) {
        //     console.error(event);
        //     return this.onerror && this.onerror(event);
        // }
    }


    // 发送心跳
    _sendHeartbeat() {
        return this._tryReConnection()
            .then(() => {
                
                this._socket.send(this._param);
                // console.log("发送心跳：",this._param)
            })
            .catch(e => {
                if (this.onerror)
                    this.onerror(e);
            });
    }

    /**
     * 检查连接是否可用, 并在不可用时重连
     */
    checkAvailable() {
        return this._tryReConnection();
    }

    close() {
        this._beat && clearInterval(this._beat);
        this._offline = true;
        return this._socket.close();
    }
    offline() {
        this._offline = true;
        clearInterval(this._beat);
        this._beat = null;
        return Promise.resolve(true);
    }
    online() {
        this._offline = false;
        this.resetHeartbeat();
        return this._tryReConnection().then(() => true);
    }
    // 重置心跳
    resetHeartbeat() {
        this._beat && clearInterval(this._beat);
        this._beat = setInterval(() => this._sendHeartbeat(), this._interval);
    }
   
    send(data) {
        // this.resetHeartbeat();
        this._tryReConnection().then(() => {
            data = typeof data == 'string' ? data : JSON.stringify(data);
            this._socket.send(data);
        });
    }

}



export { GatewayImpl };